<?php
/**
 * Abstract Class --  Mapper
 * 
 * 
 * @author Sam Xiao
 * @since 1.0
 *
 */
abstract class HashMapper extends AMapper
{
    
    
    protected $hashPrimary  = 'id';
    protected $hashName     = 'name'; 
    protected $hashValue    = 'value';
    protected $hashAttributeNames = array();
    
    protected function hashAttributeNames(){
        $attrNames = array();
        $hashValidators = $this->getValidators();
        foreach ($hashValidators as $validators){
            $className = get_class($validators);
            switch ($className){
                case 'HashAttribute':
                    foreach ($validators->attributes as $value){
                        $attrNames[$value] = $value;
                    }
                break;
                case 'HashNameAttribute':
                    $this->hashName = $validators->attributes[0];
                break;
                case 'HashValueAttribute':
                    $this->hashValue = $validators->attributes[0];
                break;
                case 'HashPrimaryAttribute':
                    $this->hashPrimary = $validators->attributes[0];
                    //$attrNames[$this->hashPrimary] = $this->hashPrimary;
                    break;
            }
            
        }
        $this->hashAttributeNames = $attrNames;
        return $this->hashAttributeNames;
    }
    
    public function getMetaData(){
        $metaData = parent::getMetaData();
        $metaData->columns = array_merge($metaData->columns,$this->hashAttributeNames());
        return $metaData;
    }
    
    public function hashAll($primary){
        $this->{$this->hashPrimary} = $primary;
        $criteria = new CDbCriteria();
        $criteria->compare($this->hashPrimary,$primary);
        $findAll = $this->findAll($criteria);
        $tempHash = array();
        if (!empty($findAll)){
            foreach ($findAll as $value){
                $tempHash[$value->{$this->hashName}] = $value->{$this->hashValue};
            }
            $this->attributes = $tempHash;
        }
        return $tempHash;
    }
    
    protected function hashKeySave($saveAttributes){
        $querySql = null;
        foreach ($saveAttributes as $key => $value){
            $hasKeySaveSql = 'INSERT INTO
        '.$this->tableName().'
        ('.$this->hashPrimary.','.$this->hashName.','.$this->hashValue.')
        VALUES ('.$this->{$this->hashPrimary}.',"'.$key.'","'.$value.'")
        ON DUPLICATE KEY UPDATE
        '.$this->hashValue.' = "'.$value.'"
        ';
            $querySql .= $hasKeySaveSql.';';
        }
        //echo($querySql);
        Yii::app()->db->createCommand($querySql)->execute();
    }
    
    public function hashSave(){
        $saveAttributes = array_intersect_key($this->attributes,$this->hashAttributeNames);
        $this->hashKeySave($saveAttributes);
    }
    
    public function findByPk($pk,$condition='',$params=array())
    {
        Yii::trace(get_class($this).'.findByPk()','system.db.ar.CActiveRecord');
        $this->hashAll($pk);
        return $this;
    }
    
    public function findByAttributes($attributes,$condition='',$params=array())
    {
        Yii::trace(get_class($this).'.findByAttributes()','system.db.ar.CActiveRecord');
        $this->hashAll($attributes[$this->hashPrimary]);
        return $this;
    }
    
    public function save($runValidation=true,$attributes=null){
		if(!$runValidation || $this->validate($attributes))
			return $this->hashSave();
		else
			return false;
	}
}